package cn.kgc.security;

import cn.kgc.entity.CustomerUser;
import cn.kgc.entity.Users;
import cn.kgc.service.MenusService;
import cn.kgc.service.UsersService;
import cn.kgc.util.RedisUtil;
import cn.kgc.util.resultutil.ResultConstant;
import cn.kgc.util.resultutil.exception.HttpException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

import static cn.kgc.util.SystemConstant.REDIS_PRE_AUTHORITIES;

/**
 * @author YC
 * SpringSecurity中，UserDetailsService接口用于加载用户特定的数据
 */
@Service
public class UsersDetailServiceImpl implements UserDetailsService {

    @Resource
    private UsersService usersService;
    @Resource
    private MenusService menusService;
    @Resource
    private RedisUtil redisUtil;

    /**
     * 根据用户名查询用户信息
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 查询用户信息
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getUserName, username);
        // 通过用户名查询用户，SpringSecurity内部会自动将加密的密文和用户输入的原文进行比较
        Users users = usersService.getOne(wrapper);
        if (users == null) {
            throw new HttpException(ResultConstant.LOGIN_ERROR);
        }
        // 查询用户权限信息（此项目中是用户的按钮权限）
        List<SimpleGrantedAuthority> authorities = menusService.getAuthoritiesByUserId(users.getUserId());
        // 存储到Redis（如果使用缓存，切记在修改权限时清除缓存）
        redisUtil.set(REDIS_PRE_AUTHORITIES + users.getRoleId(), authorities);
        // 返回用户信息（SpringSecurity需要的信息，CustomerUser中封装了项目中的User信息和权限信息）
        return new CustomerUser(users, authorities);
    }

}
